import {Card, CARD_INVALID, CARD_TYPE, Comb, GET_WEIGHT} from "./GameDefine_nbddz";

function swap(arr,i,j){
    let t = arr[i];
    arr[i] = arr[j];
    arr[j] = t;
}

let xun_huan_list_3=[
    [13,14,15],//K,A,2
    [14,15,3], //A,2,3
    [15,3,4],  //2,3,4
];

let xun_huan_list_4=[
    [12,13,14,15],//Q,K,A,2
    [13,14,15,3], //K,A,2,3
    [14,15,3,4],  //A,2,3,4
    [15,3,4,5],   //2,3,4,5
];

let xun_huan_list_5=[
    [11,12,13,14,15], //J,Q,K,A,2
    [12,13,14,15,3],  //Q,K,A,2,3
    [13,14,15,3,4],   //K,A,2,3,4
    [14,15,3,4,5],    //A,2,3,4,5
    [15,3,4,5,6],     //2,3,4,5,6
];

let xun_huan_list_6=[
    [10,11,12,13,14,15], //10,J,Q,K,A,2
    [11,12,13,14,15,3],  //J,Q,K,A,2,3
    [12,13,14,15,3,4],   //Q,K,A,2,3,4
    [13,14,15,3,4,5],    //K,A,2,3,4,5
    [14,15,3,4,5,6],     //A,2,3,4,5,6
    [15,3,4,5,6,7],      //2,3,4,5,6,7
];

export class GameLogic_nbddz{
    allcards;
    index;
    cai_shen  = [];
    init(){
        this.cai_shen  = [];
        this.cai_shen.push(Card.getCard(Card.COLOR.JOKER,Card.SIZE._BJOKER));
        this.cai_shen.push(Card.getCard(Card.COLOR.JOKER,Card.SIZE._RJOKER));
    }

    constructor(){
        this.reset();
    }

    reset(){
        this.index = 0;
        this.allcards = [
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
            0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
            0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
            0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
            0x4e, 0x4f,
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
            0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
            0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
            0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
            0x4e, 0x4f,
        ];
    }

    // 洗牌
    public suffer() {
        var cards = this.allcards;
        for (var i = 0; i < cards.length; i++) {
            var lastIndex = cards.length - 1 - i;
            var index = Math.floor(Math.random() * lastIndex);
            [cards[index],cards[lastIndex]] = [cards[lastIndex],cards[index]];
        }
    }

    // 洗牌
    public suffer_plus() {
        var cards = this.allcards;
        for (var i = 0; i < 1000; i++) {
            var index1 = Math.floor(Math.random() * cards.length);
            var index2 = Math.floor(Math.random() * cards.length);
            [cards[index1],cards[index2]] = [cards[index1],cards[index2]];
        }
    }

    /**
     * 获取下一张扑克牌
     */
    public getACard():number {
        return this.allcards[this.index++];
    }

    //获得扑克的牌面大小
    get_card_size(byte_card){
        if (Card.getSize(byte_card) == Card.SIZE._A)
            return 14;
        else if (Card.getSize(byte_card) == Card.SIZE._2)
            return 15;
        else if (Card.getSize(byte_card) == Card.SIZE._BJOKER)
            return 16;
        else if (Card.getSize(byte_card) == Card.SIZE._RJOKER)
            return 17;
        else
            return Card.getSize(byte_card);
    }

    get_default_size(byte_card){
        return Card.getSize(byte_card);
    }

    get_next_card(card){
        let color = Card.getColor(card);
        let size = Card.getSize(card);
        if(size == Card.SIZE._K) return Card.getCard(color,Card.SIZE._A);
        else return Card.getCard(color,size + 1);
    }

    get_last_card(card){
        let color = Card.getColor(card);
        let size = Card.getSize(card);
        if(size == Card.SIZE._A) return Card.getCard(color,Card.SIZE._K);
        else return Card.getCard(color,size - 1);
    }

    is_sub_cards(cards:Array<number>,sub:Array<number>){
        let bIndex = this.switchToIndex(cards);
        let bIndex2 = this.switchToIndex(sub);
        for(let i = 0 ; i<bIndex.length;i++){
            if(bIndex[i] < bIndex2[i]){
                return false;
            }
        }
        return true;
    }

    del_sub_cards(cards:Array<number>,sub:Array<number>){
        for(let i=0;i<sub.length;i++){
            for(let j=0;j<cards.length;j++){
                if(sub[i] == cards[j]){
                    cards.splice(j,1);
                    break;
                }
            }
        }
    }

    //通过大小排序，从大到小
    sort_cards_by_size_down(byte_cards:Array<number>){
        if (byte_cards.length == 0)
            return;
        for (let i=0; i<byte_cards.length; i++)
        {
            for (let j=i+1; j<byte_cards.length; j++)
            {
                if (this.get_card_size(byte_cards[i]) <
                    this.get_card_size(byte_cards[j]))
                {
                    swap(byte_cards,i,j);
                }
                else if (this.get_card_size(byte_cards[i]) == this.get_card_size(byte_cards[j])
                    && Card.getColor(byte_cards[i]) < Card.getColor(byte_cards[j]))
                {
                    swap(byte_cards,i,j);
                }
            }
        }
    }

    //通过大小排序，从小到大
    sort_cards_by_size_up(byte_cards:Array<number>){
        if (byte_cards.length == 0)
            return;
        for (let i=0; i<byte_cards.length; i++)
        {
            for (let j=i+1; j<byte_cards.length; j++)
            {
                if (this.get_card_size(byte_cards[i]) >
                    this.get_card_size(byte_cards[j]))
                {
                    swap(byte_cards,i,j);
                }
                else if (this.get_card_size(byte_cards[i]) == this.get_card_size(byte_cards[j])
                    && Card.getColor(byte_cards[i]) > Card.getColor(byte_cards[j]))
                {
                    swap(byte_cards,i,j);
                }
            }
        }
    }

    //连牌使用
    sort_cards_by_default_size(byte_cards:Array<number>){
        if (byte_cards.length == 0)
            return;
        for (let i=0; i<byte_cards.length; i++)
        {
            for (let j=i+1; j<byte_cards.length; j++)
            {
                if (this.get_default_size(byte_cards[i]) >
                    this.get_default_size(byte_cards[j]))
                {
                    swap(byte_cards,i,j);
                }
                else if (this.get_default_size(byte_cards[i]) == this.get_default_size(byte_cards[j])
                    && Card.getColor(byte_cards[i]) > Card.getColor(byte_cards[j]))
                {
                    swap(byte_cards,i,j);
                }
            }
        }
    }

    //去掉牌面大小相同的牌, 得到的容器CARD_SIZE有效
    get_no_same_size(byte_cards:Array<number>,isDefault?:boolean){
        if(isDefault) this.sort_cards_by_default_size(byte_cards);
        else this.sort_cards_by_size_up(byte_cards);
        let cards = [];
        for(let i=0;i<byte_cards.length;i++){
            if (0 == i)
            {
                cards.push(byte_cards[i]);
            }
            else
            {
                //不相等的才放进去
                if (Card.getSize(byte_cards[i]) != Card.getSize(cards[cards.length-1]))
                {
                    cards.push(byte_cards[i]);
                }
            }
        }
        return cards;
    }

    get_same_size_card(byte_cards:Array<number>,byte_same){
        let same_cards = [];
        for (let i=0; i<byte_cards.length; i++){
            if (Card.getSize(byte_cards[i]) == Card.getSize(byte_same))
            {
                same_cards.push(byte_cards[i]);
            }
        }
        return same_cards;
    }

    get_all_same_size_cards(byte_cards:Array<number>,isDefault?:boolean){
        let no_same_cards = this.get_no_same_size(byte_cards,isDefault);
        let all_same_size_cards = [];
        for(let i=0;i<no_same_cards.length;i++){
            let same_cards = this.get_same_size_card(byte_cards,no_same_cards[i]);
            all_same_size_cards.push(same_cards);
        }
        return all_same_size_cards;
    }

    switchToIndex(byte_cards:Array<number>){
        let bIndex:number[] = Array(Card.SIZE.COUNT).fill(0);
        for(let i = 0 ; i < byte_cards.length ;i++) {
            bIndex[Card.getSize(byte_cards[i])]++;
        }
        return bIndex;
    }

    is_joker(byte_card):boolean{
        return ((Card.getSize(byte_card) == Card.SIZE._BJOKER) || (Card.getSize(byte_card) == Card.SIZE._RJOKER));
    }

    is_exist_joker(byte_cards:Array<number>):boolean{
        for (let i = 0; i < byte_cards.length; i++)
        {
            if (this.is_joker(byte_cards[i]))
            {
                return true;
            }
        }
        return false;
    }

    is_exist_er(byte_cards:Array<number>):boolean{
        for (let i = 0; i < byte_cards.length; i++)
        {
            if (Card.getSize(byte_cards[i]) == Card.SIZE._2)
            {
                return true;
            }
        }
        return false;
    }

    is_no_joker_bomb(byte_cards:Array<number>):boolean{
        if (this.is_exist_joker(byte_cards))
        {
            return false;
        }
        //得到不重复大小的牌
        let no_same_size_cards = this.get_no_same_size(byte_cards);
        if (no_same_size_cards.length == 1)
        {
            return true;
        }
        return false;
    }

    get_no_cai_shen_cards(byte_cards:Array<number>){
        let no_cai_shen = [];
        for(let i=0;i<byte_cards.length;i++){
            let flag = true;
            for(let j=0;j<this.cai_shen.length;j++){
                if(byte_cards[i] == this.cai_shen[j]){
                    flag = false;
                    break;
                }
            }
            if(flag) no_cai_shen.push(byte_cards[i]);
        }
        return no_cai_shen;
    }

    get_cai_shen_cards(byte_cards:Array<number>){
        let cai_shen = [];
        for(let i=0;i<byte_cards.length;i++){
            let flag = false;
            for(let j=0;j<this.cai_shen.length;j++){
                if(byte_cards[i] == this.cai_shen[j]){
                    flag = true;
                    break;
                }
            }
            if(flag) cai_shen.push(byte_cards[i]);
        }
        return cai_shen;
    }
    //////////////////////////////////////////////////////////////////////////////////////
    //获取这手牌可以组成的牌型
    get_all_combs(byte_cards:Array<number>):Array<Comb>{
        this.sort_cards_by_size_up(byte_cards);
        let combs = [];
        let len = byte_cards.length;
        //单张
        if(len == 1){
            combs.push(new Comb(CARD_TYPE.DAN_ZHANG,byte_cards[0],byte_cards));
            return combs;
        }

        if(this.is_tian_wang(byte_cards)){
            combs.push(new Comb(CARD_TYPE.TIAN_WANG,byte_cards[0],byte_cards));
            return combs;
        }

        let no_cai_shen = this.get_no_cai_shen_cards(byte_cards);
        let cai_shen_count = byte_cards.length - no_cai_shen.length;
        if(cai_shen_count == 0){
            let type = this.get_n_zhang_bomb_type(byte_cards);
            if(type != CARD_TYPE.NULL){
                combs.push(new Comb(type,byte_cards[0],byte_cards));
                return combs;
            }
            if(len == 2 && this.is_dui_zi(byte_cards)){
                combs.push(new Comb(CARD_TYPE.DUI_ZI,byte_cards[0],byte_cards));
                return combs;
            }else if(len == 3 && this.is_san_zhang(byte_cards)){
                combs.push(new Comb(CARD_TYPE.SAN_ZHANG,byte_cards[0],byte_cards));
                return combs;
            }else if(len == 5){
                let card = this.is_san_dai_dui(byte_cards);
                if(card!=CARD_INVALID){
                    combs.push(new Comb(CARD_TYPE.SAN_DAI_DUI,card,byte_cards));
                    return combs;
                }
            }else{
                if(this.is_er_shun(byte_cards) || this.is_er_shun_123(byte_cards)){
                    combs.push(new Comb(CARD_TYPE.ER_SHUN,byte_cards[0],byte_cards));
                    return combs;
                }
                if(this.is_san_shun(byte_cards) || this.is_san_shun_123(byte_cards)){
                    combs.push(new Comb(CARD_TYPE.SAN_SHUN,byte_cards[0],byte_cards));
                    return combs;
                }
                let max_card = this.is_fei_ji_wing(byte_cards);
                if(max_card != CARD_INVALID){
                    combs.push(new Comb(CARD_TYPE.FEI_JI_WIN,max_card,byte_cards));
                    return combs;
                }
            }
        }else{
            let type = this.get_n_zhang_bomb_type_cai_shen(no_cai_shen,cai_shen_count);
            if(type != CARD_TYPE.NULL){
                combs.push(new Comb(type,byte_cards[0],byte_cards));
                return combs;
            }
            if(len == 2 && this.is_dui_zi_cai_shen(cai_shen_count)){
                combs.push(new Comb(CARD_TYPE.DUI_ZI,byte_cards[0],byte_cards));
                return combs;
            }else if(len == 3 && this.is_san_zhang_cai_shen(no_cai_shen,cai_shen_count)){
                combs.push(new Comb(CARD_TYPE.SAN_ZHANG,byte_cards[0],byte_cards));
                return combs;
            }else if(len == 5){
                let card = this.is_san_dai_dui_cai_shen(no_cai_shen,cai_shen_count);
                if(card!=CARD_INVALID){
                    combs.push(new Comb(CARD_TYPE.SAN_DAI_DUI,card,byte_cards));
                    return combs;
                }
            }else{
                let max_card = this.is_er_shun_cai_shen(no_cai_shen,cai_shen_count)
                if(max_card != CARD_INVALID){
                    combs.push(new Comb(CARD_TYPE.ER_SHUN,max_card,byte_cards));
                }
                max_card = this.is_er_shun_cai_shen_123(no_cai_shen,cai_shen_count)
                if(max_card != CARD_INVALID){
                    combs.push(new Comb(CARD_TYPE.SAN_SHUN,max_card,byte_cards));
                }
                max_card = this.is_san_shun_cai_shen(no_cai_shen,cai_shen_count)
                if(max_card != CARD_INVALID){
                    combs.push(new Comb(CARD_TYPE.SAN_SHUN,max_card,byte_cards));
                }
                max_card = this.is_san_shun_cai_shen_123(no_cai_shen,cai_shen_count)
                if(max_card != CARD_INVALID){
                    combs.push(new Comb(CARD_TYPE.SAN_SHUN,max_card,byte_cards));
                }
                max_card = this.is_fei_ji_wing_cai_shen(no_cai_shen,cai_shen_count);
                if(max_card != CARD_INVALID){
                    combs.push(new Comb(CARD_TYPE.FEI_JI_WIN,max_card,byte_cards));
                    return combs;
                }
            }
        }

        return combs;
    }

    compare_two_comb(comb1:Comb,comb2:Comb):boolean{
        let type1 = comb1.type;
        let type2 = comb2.type;
        if (type1 == CARD_TYPE.NULL || type2 == CARD_TYPE.NULL)
        {
            return false;
        }

        //同类型牌型比较最小的一张牌
        if(type1 == type2){
            if(type1<CARD_TYPE.SI_ZHA && comb1.cards.length != comb2.cards.length){
                return false;
            }
            if(type1==CARD_TYPE.ER_SHUN || type1==CARD_TYPE.SAN_SHUN || type1==CARD_TYPE.FEI_JI_WIN){
                return this.get_default_size(comb1.max_card) > this.get_default_size(comb2.max_card);
            }else{
                return this.get_card_size(comb1.max_card) > this.get_card_size(comb2.max_card);
            }
        }

        // 四线以下不能互压
        if(type1<CARD_TYPE.SI_ZHA){
            return false;
        }

        return GET_WEIGHT(type1) > GET_WEIGHT(type2);
    }

    //是否是同类型的牌组
    is_simple_comb(comb1:Comb,comb2:Comb):boolean{
        let type1 = comb1.type;
        let type2 = comb2.type;
        if(type1 == type2){
            if(type1<CARD_TYPE.SI_ZHA && comb1.cards.length != comb2.cards.length){
                return false;
            }
            return this.get_card_size(comb1.max_card) == this.get_card_size(comb2.max_card);
        }
        return false;
    }

    checkComb(comb:Comb):boolean{
        if(comb == null) return false;
        let combs = this.get_all_combs(comb.cards);
        for(let j=0;j<combs.length;j++){
            if(combs[j].type == comb.type){
                return true;
            }
        }
        return false;
    }

    get_bigger_comb(byte_cards:Array<number>,preComb?:Comb):Comb{
        console.log("get_bigger_comb1",byte_cards,preComb);
        let combs = this.get_all_combs(byte_cards);
        if(preComb == null){
            console.log("get_bigger_comb2",combs[0]);
            return combs[0];
        }
        for(let i=0;i<combs.length;i++){
            if(this.compare_two_comb(combs[i],preComb)){
                console.log("get_bigger_comb3",combs[i]);
                return combs[i];
            }
        }
        return null;
    }

    //对子
    is_dui_zi(byte_cards:Array<number>){
        if (byte_cards.length != 2)
        {
            return false;
        }

        if (Card.getSize(byte_cards[0]) == Card.getSize(byte_cards[1]))
        {
            return true;
        }

        return false;
    }

    //财神对子
    is_dui_zi_cai_shen(caishen:number){
        if(caishen>=1) return true;
        return false;
    }

    //三张
    is_san_zhang(byte_cards:Array<number>){
        if (byte_cards.length != 3)
        {
            return false;
        }

        if (Card.getSize(byte_cards[0]) == Card.getSize(byte_cards[1]) &&
            Card.getSize(byte_cards[0]) == Card.getSize(byte_cards[2]) &&
            Card.getSize(byte_cards[1]) == Card.getSize(byte_cards[2]))
        {
            return true;
        }

        return false;
    }

    //三张财神
    is_san_zhang_cai_shen(no_cai_shen_cards:Array<number>,caishen:number){
        if(caishen>=2) return true;
        if (caishen == 1 && Card.getSize(no_cai_shen_cards[0]) == Card.getSize(no_cai_shen_cards[1]))
        {
            return true;
        }
        return false;
    }

    //二顺
    is_er_shun(byte_cards:Array<number>,minLen?:number){
        //三连对, 或者以上的连对
        minLen = minLen || 6;
        if (byte_cards.length < minLen || (byte_cards.length%2 != 0))
        {
            return false;
        }
        //不能王
        if (this.is_exist_joker(byte_cards) ||
            this.is_exist_er(byte_cards))
        {
            return false;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(byte_cards);
        let temp_card = 0;
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if (card_item.length != 2)
            {
                return false;
            }
            if (temp_card == 0)
            {
                temp_card = this.get_card_size(card_item[0]);
            }
            else
            {
                if (this.get_card_size(card_item[0]) - temp_card != 1)
                {
                    return false;
                }
                temp_card = this.get_card_size(card_item[0]);
            }
        }
        return true;
    }

    //财神二顺
    is_er_shun_cai_shen(no_cai_shen_cards:Array<number>,caishen:number,minLen?:number):number{
        let count = no_cai_shen_cards.length + caishen;
        minLen = minLen||6;
        //三连对, 或者以上的连对
        if (count < minLen || (count%2 != 0) || count > 24)
        {
            return CARD_INVALID;
        }
        //不能有2， 王
        if (this.is_exist_joker(no_cai_shen_cards) ||
            this.is_exist_er(no_cai_shen_cards))
        {
            return CARD_INVALID;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(no_cai_shen_cards);
        let temp_card = 0;
        let need_cai_shen = 0;
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if (card_item.length > 2)
            {
                return CARD_INVALID;
            }

            if(card_item.length == 1){
                need_cai_shen++;
            }

            if (temp_card == 0)
            {
                temp_card = this.get_card_size(card_item[0]);
            }
            else
            {
                let diff = this.get_card_size(card_item[0]) - temp_card;
                if (diff != 1)
                {
                    need_cai_shen+=2*(diff-1);
                }
                temp_card = this.get_card_size(card_item[0]);
            }
            if(need_cai_shen>caishen) return CARD_INVALID;
        }

        if(caishen>need_cai_shen && (caishen-need_cai_shen)%2 == 0) {
            let max_size = this.get_card_size(no_cai_shen_cards[no_cai_shen_cards.length - 1]);
            let size_A = 14;
            let remain = (caishen - need_cai_shen)/2;
            let diff = remain - (size_A - max_size);
            if(diff>0){
                let size = this.get_card_size(no_cai_shen_cards[0]) - diff;
                if(size != Card.SIZE._2){
                    return Card.getCard(Card.COLOR.FANG, size);
                } else {
                    return CARD_INVALID
                }
            }else{
                return no_cai_shen_cards[0];
            }
        }else if(caishen == need_cai_shen){
            return no_cai_shen_cards[0];
        }else{
            return CARD_INVALID
        }
    }

    //二顺 支持123 不支持 QKA
    is_er_shun_123(byte_cards:Array<number>,minLen?:number){
        //三连对, 或者以上的连对
        minLen = minLen || 6
        if (byte_cards.length < minLen || (byte_cards.length%2 != 0))
        {
            return false;
        }
        //不能王
        if (this.is_exist_joker(byte_cards))
        {
            return false;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(byte_cards,true);
        let temp_card = 0;
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if (card_item.length != 2)
            {
                return false;
            }
            if (temp_card == 0)
            {
                temp_card = this.get_default_size(card_item[0]);
            }
            else
            {
                if (this.get_default_size(card_item[0]) - temp_card != 1)
                {
                    return false;
                }
                temp_card = this.get_default_size(card_item[0]);
            }
        }
        return true;
    }

    //财神二顺 支持123 不支持 QKA
    is_er_shun_cai_shen_123(no_cai_shen_cards:Array<number>,caishen:number,minLen?:number):number{
        let count = no_cai_shen_cards.length + caishen;
        minLen = minLen || 6
        //三连对, 或者以上的连对
        if (count < minLen || (count%2 != 0) || count > 24)
        {
            return CARD_INVALID;
        }
        //不能有2， 王
        if (this.is_exist_joker(no_cai_shen_cards))
        {
            return CARD_INVALID;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(no_cai_shen_cards,true);
        let temp_card = 0;
        let need_cai_shen = 0;
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if (card_item.length > 2)
            {
                return CARD_INVALID;
            }

            if(card_item.length == 1){
                need_cai_shen++;
            }

            if (temp_card == 0)
            {
                temp_card = this.get_default_size(card_item[0]);
            }
            else
            {
                let diff = this.get_default_size(card_item[0]) - temp_card;
                if (diff != 1)
                {
                    need_cai_shen+=2*(diff-1);
                }
                temp_card = this.get_default_size(card_item[0]);
            }
            if(need_cai_shen>caishen) return CARD_INVALID;
        }

        if(caishen>need_cai_shen && (caishen-need_cai_shen)%2 == 0) {
            let max_size = this.get_card_size(no_cai_shen_cards[no_cai_shen_cards.length - 1]);
            let size_A = 14;
            let remain = (caishen - need_cai_shen)/2;
            let diff = remain - (size_A - max_size);
            if(diff>0){
                let size = this.get_card_size(no_cai_shen_cards[0]) - diff;
                if(size != Card.SIZE._2){
                    return Card.getCard(Card.COLOR.FANG, size);
                } else {
                    return CARD_INVALID
                }
            }else{
                return no_cai_shen_cards[0];
            }
        }else if(caishen == need_cai_shen){
            return no_cai_shen_cards[0];
        }else{
            return CARD_INVALID
        }
    }

    //三顺
    is_san_shun(byte_cards:Array<number>){
        //三连对, 或者以上的连对
        if (byte_cards.length < 6 || (byte_cards.length%3 != 0))
        {
            return false;
        }
        //不能有2， 王
        if (this.is_exist_joker(byte_cards) ||
            this.is_exist_er(byte_cards))
        {
            return false;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(byte_cards);
        let temp_card = 0;
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if (card_item.length != 3)
            {
                return false;
            }
            if (temp_card == 0)
            {
                temp_card = this.get_card_size(card_item[0]);
            }
            else
            {
                if (this.get_card_size(card_item[0]) - temp_card != 1)
                {
                    return false;
                }
                temp_card = this.get_card_size(card_item[0]);
            }
        }
        return true;
    }

    //财神三顺
    is_san_shun_cai_shen(no_cai_shen_cards:Array<number>,caishen:number):number{
        let count = no_cai_shen_cards.length + caishen;
        //三连三张, 或者以上的
        if (count < 6 || (count%3 != 0) || count > 36)
        {
            return CARD_INVALID;
        }

        //不能有2， 王
        if (this.is_exist_joker(no_cai_shen_cards) ||
            this.is_exist_er(no_cai_shen_cards))
        {
            return CARD_INVALID;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(no_cai_shen_cards);
        let temp_card = 0;
        let need_cai_shen = 0;
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if (card_item.length > 3)
            {
                return CARD_INVALID;
            }

            if(card_item.length < 3){
                need_cai_shen += 3 - card_item.length;
            }

            if (temp_card == 0)
            {
                temp_card = this.get_card_size(card_item[0]);
            }
            else
            {
                let diff = this.get_card_size(card_item[0]) - temp_card;
                if (diff != 1)
                {
                    need_cai_shen+=3*(diff-1);
                }
                temp_card = this.get_card_size(card_item[0]);
            }
            if(need_cai_shen>caishen) return CARD_INVALID;
        }

        if(caishen>need_cai_shen && (caishen-need_cai_shen)%3 == 0) {
            let max_size = this.get_card_size(no_cai_shen_cards[no_cai_shen_cards.length - 1]);
            let size_A = 14;
            let remain = (caishen - need_cai_shen)/3;
            let diff = remain - (size_A - max_size);
            if(diff>0){
                let size = this.get_card_size(no_cai_shen_cards[0]) - diff;
                if(size != Card.SIZE._2){
                    return Card.getCard(Card.COLOR.FANG, size);
                } else {
                    return CARD_INVALID
                }
            }else{
                return no_cai_shen_cards[0];
            }
        }else if(caishen == need_cai_shen){
            return no_cai_shen_cards[0];
        }else{
            return CARD_INVALID
        }
    }

    //三顺 支持123 不支持 QKA
    is_san_shun_123(byte_cards:Array<number>){
        //三连对, 或者以上的连对
        if (byte_cards.length < 6 || (byte_cards.length%3 != 0))
        {
            return false;
        }
        //不能有王
        if (this.is_exist_joker(byte_cards))
        {
            return false;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(byte_cards,true);
        let temp_card = 0;
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if (card_item.length != 3)
            {
                return false;
            }
            if (temp_card == 0)
            {
                temp_card = this.get_default_size(card_item[0]);
            }
            else
            {
                if (this.get_default_size(card_item[0]) - temp_card != 1)
                {
                    return false;
                }
                temp_card = this.get_default_size(card_item[0]);
            }
        }
        return true;
    }

    //财神三顺 支持123 不支持 QKA
    is_san_shun_cai_shen_123(no_cai_shen_cards:Array<number>,caishen:number):number{
        let count = no_cai_shen_cards.length + caishen;
        //三连三张, 或者以上的
        if (count < 6 || (count%3 != 0) || count > 36)
        {
            return CARD_INVALID;
        }

        //不能有2， 王
        if (this.is_exist_joker(no_cai_shen_cards))
        {
            return CARD_INVALID;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(no_cai_shen_cards,true);
        let temp_card = 0;
        let need_cai_shen = 0;
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if (card_item.length > 3)
            {
                return CARD_INVALID;
            }

            if(card_item.length < 3){
                need_cai_shen += 3 - card_item.length;
            }

            if (temp_card == 0)
            {
                temp_card = this.get_default_size(card_item[0]);
            }
            else
            {
                let diff = this.get_default_size(card_item[0]) - temp_card;
                if (diff != 1)
                {
                    need_cai_shen+=3*(diff-1);
                }
                temp_card = this.get_default_size(card_item[0]);
            }
            if(need_cai_shen>caishen) return CARD_INVALID;
        }

        if(caishen>need_cai_shen && (caishen-need_cai_shen)%3 == 0) {
            let max_size = this.get_card_size(no_cai_shen_cards[no_cai_shen_cards.length - 1]);
            let size_A = 14;
            let remain = (caishen - need_cai_shen)/3;
            let diff = remain - (size_A - max_size);
            if(diff>0){
                let size = this.get_card_size(no_cai_shen_cards[0]) - diff;
                if(size != Card.SIZE._2){
                    return Card.getCard(Card.COLOR.FANG, size);
                } else {
                    return CARD_INVALID
                }
            }else{
                return no_cai_shen_cards[0];
            }
        }else if(caishen == need_cai_shen){
            return no_cai_shen_cards[0];
        }else{
            return CARD_INVALID
        }
    }

    is_san_dai_dui(byte_cards:Array<number>):number{
        //三连对, 或者以上的连对
        if (byte_cards.length!=5)
        {
            return CARD_INVALID;
        }
        //不能有， 王
        if (this.is_exist_joker(byte_cards))
        {
            return CARD_INVALID;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(byte_cards,true);
        let san_cards = [];
        let er_cards = [];
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if (card_item.length > 3 || card_item.length<2)
            {
                return CARD_INVALID;
            }

            if(card_item.length == 3){
                san_cards = san_cards.concat(card_item)
            }
            if(card_item.length == 2){
                er_cards = er_cards.concat(card_item)
            }
        }
        if(er_cards.length/2 != san_cards.length/3){
            return CARD_INVALID;
        }
        return san_cards[0];
    }

    is_san_dai_dui_cai_shen(no_cai_shen_cards:Array<number>,caishen:number):number{
        //三连对, 或者以上的连对
        let count = no_cai_shen_cards.length + caishen;
        //三连三张, 或者以上的
        if (count !=5)
        {
            return CARD_INVALID;
        }

        //不能有， 王
        if (this.is_exist_joker(no_cai_shen_cards))
        {
            return CARD_INVALID;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(no_cai_shen_cards,);
        let san_cards = [];
        let er_cards = [];
        let yi_cards = [];
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if (card_item.length > 3)
            {
                return CARD_INVALID;
            }
            if(card_item.length == 3){
                san_cards = san_cards.concat(card_item)
            }
            if(card_item.length == 2){
                er_cards.push(card_item)
            }
            if(card_item.length == 1){
                yi_cards = yi_cards.concat(card_item)
            }
        }

        if(san_cards.length==3){
            let needCaiShen = 2-yi_cards.length-er_cards.length*2;
            if(needCaiShen==caishen){
                return san_cards[0];
            }else{
                return CARD_INVALID;
            }
        }else if(san_cards.length==0 && er_cards.length==2 && yi_cards.length<=1){
            let needCaiShen = 1-yi_cards.length;
            if(needCaiShen==caishen){
                return er_cards[1][0];
            }else{
                return CARD_INVALID;
            }
        }else if(san_cards.length==0 && er_cards.length==1 && yi_cards.length<=1){
            let needCaiShen = 3-yi_cards.length;
            if(needCaiShen==caishen){
                return er_cards[0][0];
            }else{
                return CARD_INVALID;
            }
        }else if(san_cards.length==0 && er_cards.length==0 && yi_cards.length<=2){
            let needCaiShen = 5-yi_cards.length;
            if(caishen==needCaiShen){
                return yi_cards[yi_cards.length-1];
            }else{
                return CARD_INVALID;
            }
        }
        return CARD_INVALID;
    }

    is_fei_ji_wing(byte_cards:Array<number>):number{
        //三连对, 或者以上的连对
        if (byte_cards.length < 10 || (byte_cards.length%5 != 0))
        {
            return CARD_INVALID;
        }
        //不能有2， 王
        if (this.is_exist_joker(byte_cards))
        {
            return CARD_INVALID;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(byte_cards,true);
        let san_cards = [];
        let er_cards = [];
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if (card_item.length<2)
            {
                return CARD_INVALID;
            }
            if(card_item.length>3){
                san_cards.concat(card_item.slice(0,3));
                er_cards.concat(card_item.slice(3,card_item.length));
            }
            if(card_item.length == 3){
                san_cards = san_cards.concat(card_item)
            }
            if(card_item.length == 2){
                er_cards = er_cards.concat(card_item)
            }
        }
        if(er_cards.length/2 != san_cards.length/3){
            return CARD_INVALID;
        }

        if((this.is_san_shun(san_cards) || this.is_san_shun_123(san_cards)) && (this.is_er_shun(er_cards,4) || this.is_er_shun_123(er_cards,4))){
            return san_cards[0];
        }else{
            return CARD_INVALID;
        }
    }

    private dfs_fei_ji_win_cai_shen(nLian:number,cards3:Array<number>,cards2:Array<number>,cards_pool:Array<Array<number>>,caishen:number):number{
        if(cards_pool.length==0){
            let caishen3 = nLian*3-cards3.length;
            let caishen2 = nLian*2-cards2.length;
            if(caishen3<0 || caishen2<0 || caishen3+caishen2!=caishen){
                return CARD_INVALID;
            }
            let res3 = CARD_INVALID;
            if(caishen3==0){
                if(this.is_san_shun(cards3) || this.is_san_shun_123(cards3)){
                    res3 = cards3[0];
                }
            }else{
                res3 = this.is_san_shun_cai_shen(cards3,caishen3);
                if(res3==CARD_INVALID){
                    res3 = this.is_san_shun_cai_shen_123(cards3,caishen3)
                }
            }
            if(res3==CARD_INVALID){
                return CARD_INVALID;
            }
            if(caishen2==0 &&(this.is_er_shun(cards2,4) || this.is_er_shun_123(cards2,4))){
                return res3
            }else if(caishen2>0 &&(this.is_er_shun_cai_shen(cards2,caishen2,4) || this.is_er_shun_cai_shen_123(cards2,caishen2,4))){
                return res3
            }else{
                return CARD_INVALID;
            }
        }
        let tmpCards=cards_pool.pop();
        let ret1 = this.dfs_fei_ji_win_cai_shen(nLian,cards3.concat(tmpCards),cards2,cards_pool,caishen)
        let ret2 = this.dfs_fei_ji_win_cai_shen(nLian,cards3,cards2.concat(tmpCards),cards_pool,caishen)
        cards_pool.push(tmpCards);
        if(this.get_default_size(ret1)>this.get_default_size(ret2)){
            return ret1;
        }else{
            return ret2;
        }
    }

    is_fei_ji_wing_cai_shen(no_cai_shen_cards:Array<number>,caishen:number):number{
        let count = no_cai_shen_cards.length + caishen;
        //三连三张, 或者以上的
        if (count < 10 || (count%5 != 0))
        {
            return CARD_INVALID;
        }
        let n=count/5; //需要成为n连机
        //不能有 王
        if (this.is_exist_joker(no_cai_shen_cards))
        {
            return CARD_INVALID;
        }

        let all_same_size_cards:Array<Array<number>> = this.get_all_same_size_cards(no_cai_shen_cards,false);
        let cards3:Array<number> = [];
        let cards_pool:Array<Array<number>> = [];
        //将手牌分文三张和其他牌
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let card_item:Array<number> = all_same_size_cards[i];
            if(card_item.length>3){
                cards3.concat(card_item.slice(0,3));
                cards_pool.push(card_item.slice(3,card_item.length));
            }
            if(card_item.length == 3){
                cards3 = cards3.concat(card_item)
            }
            if(card_item.length <= 2){
                cards_pool.push(card_item);
            }
        }
        return this.dfs_fei_ji_win_cai_shen(n,cards3,[],cards_pool,caishen)
    }

    //n炸无财神
    get_n_zhang_bomb_type(byte_cards:Array<number>){
        if(!this.is_no_joker_bomb(byte_cards)) return CARD_TYPE.NULL;
        switch(byte_cards.length){
            case 4:return CARD_TYPE.SI_ZHA;
            case 5:return CARD_TYPE.WU_ZHA;
            case 6:return CARD_TYPE.LIU_ZHA;
            case 7:return CARD_TYPE.QI_ZHA;
            case 8:return CARD_TYPE.BA_ZHA;
            case 9:return CARD_TYPE.JIU_ZHA;
            case 10:return CARD_TYPE.SHI_ZHA;
            case 11:return CARD_TYPE.SHI_YI_ZHA;
            case 12:return CARD_TYPE.SHI_ER_ZHA;
            default:return CARD_TYPE.NULL;
        }
    }

    //n炸有财神
    get_n_zhang_bomb_type_cai_shen(no_cai_shen_cards:Array<number>,caishen:number){
        if(!this.is_no_joker_bomb(no_cai_shen_cards)) return CARD_TYPE.NULL;
        switch(no_cai_shen_cards.length + caishen){
            case 4:return CARD_TYPE.SI_ZHA;
            case 5:return CARD_TYPE.WU_ZHA;
            case 6:return CARD_TYPE.LIU_ZHA;
            case 7:return CARD_TYPE.QI_ZHA;
            case 8:return CARD_TYPE.BA_ZHA;
            case 9:return CARD_TYPE.JIU_ZHA;
            case 10:return CARD_TYPE.SHI_ZHA;
            case 11:return CARD_TYPE.SHI_YI_ZHA;
            case 12:return CARD_TYPE.SHI_ER_ZHA;
            default:return CARD_TYPE.NULL;
        }
    }

    //天王炸
    is_tian_wang(byte_cards:Array<number>){
        if(byte_cards.length != 4) return false;

        if (this.is_joker(byte_cards[0]) &&
            this.is_joker(byte_cards[1]) &&
            this.is_joker(byte_cards[2]) &&
            this.is_joker(byte_cards[3]))
        {
            return true;
        }
        return false;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //提示功能2
    hint_out(byte_cards:Array<number>,preComb?:Comb):Array<Comb>{
        this.sort_cards_by_size_up(byte_cards);
        if(preComb == null){
            let combs = this.get_all_combs(byte_cards);
            if(combs.length>0) return combs;
            let no_cai_shen = this.get_no_cai_shen_cards(byte_cards);
            let cai_shen = this.get_cai_shen_cards(byte_cards);
            combs = combs.concat(this.get_all_hint_yi_zhang(no_cai_shen,cai_shen));
            combs = combs.concat(this.get_all_hint_er_zhang(no_cai_shen,cai_shen));
            combs = combs.concat(this.get_all_hint_san_zhang(no_cai_shen,cai_shen));
            combs = combs.concat(this.get_all_hint_er_shun(no_cai_shen,cai_shen));
            combs = combs.concat(this.get_all_hint_san_shun(no_cai_shen,cai_shen));
            combs = combs.concat(this.get_all_hint_normal_boom(no_cai_shen,cai_shen));
            return this.get_no_simple_combs(combs);
        }

        let combs:Array<Comb> = [];
        let no_cai_shen = this.get_no_cai_shen_cards(byte_cards);
        let cai_shen = this.get_cai_shen_cards(byte_cards);
        if(preComb.type == CARD_TYPE.DAN_ZHANG){
            combs = combs.concat(this.get_all_hint_yi_zhang(no_cai_shen,cai_shen));
        }

        if(preComb.type == CARD_TYPE.DUI_ZI){
            combs = combs.concat(this.get_all_hint_er_zhang(no_cai_shen,cai_shen));
        }

        if(preComb.type == CARD_TYPE.SAN_ZHANG){
            combs = combs.concat(this.get_all_hint_san_zhang(no_cai_shen,cai_shen));
        }

        if(preComb.type == CARD_TYPE.SAN_DAI_DUI){
            combs = combs.concat(this.get_all_hint_san_dai_dui(no_cai_shen,cai_shen));
        }

        if(preComb.type == CARD_TYPE.ER_SHUN){
            combs = combs.concat(this.get_all_hint_er_shun(no_cai_shen,cai_shen));
        }

        if(preComb.type == CARD_TYPE.SAN_SHUN){
            combs = combs.concat(this.get_all_hint_san_shun(no_cai_shen,cai_shen));
        }

        if(preComb.type == CARD_TYPE.FEI_JI_WIN){
            combs = combs.concat(this.get_all_hint_fei_ji_win(no_cai_shen,cai_shen));
        }
        combs = combs.concat(this.get_all_hint_normal_boom(no_cai_shen,cai_shen));

        let result = [];
        for(let i=0;i<combs.length;i++){
            if(this.compare_two_comb(combs[i],preComb)){
                result.push(combs[i]);
            }
        }

        return result;
    }


    get_no_simple_combs(combs:Array<Comb>):Array<Comb>{
        let no_simple_combs = [];
        for(let i=0;i<combs.length;i++){
            let flag = true;
            for(let j=0;j<no_simple_combs.length;j++){
                if(this.is_simple_comb(combs[i],no_simple_combs[j])){
                    flag = false;
                    break;
                }
            }
            if(flag) no_simple_combs.push(combs[i]);
        }
        return no_simple_combs;
    }

    get_all_hint_yi_zhang(no_cai_shen_cards:Array<number>,cai_shen:Array<number>):Array<Comb>{
        let combs = [];
        if(no_cai_shen_cards.length > 0){
            let same_size_cards = this.get_all_same_size_cards(no_cai_shen_cards);
            for (let i = 0; i < same_size_cards.length; i++)
            {
                //优先相同张数的
                let cards_item = same_size_cards[i];
                if (cards_item.length == 1)
                {
                    combs.push(new Comb(CARD_TYPE.DAN_ZHANG,cards_item[0],cards_item));
                }
            }

            for (let i = 0; i < same_size_cards.length; i++)
            {
                //不拆炸弹
                let cards_item = same_size_cards[i];
                if (cards_item.length >1 && cards_item.length < 4)
                {
                    combs.push(new Comb(CARD_TYPE.DAN_ZHANG,cards_item[0],cards_item.slice(0,1)));
                }
            }
        }
        //最后添加财神
        if(cai_shen.length > 0){
            let same_size_cards = this.get_all_same_size_cards(cai_shen);
            for (let i = 0; i < same_size_cards.length; i++)
            {
                let cards_item = same_size_cards[i];
                combs.push(new Comb(CARD_TYPE.DAN_ZHANG,cards_item[0],cards_item.slice(0,1)));
            }
        }
        return combs;
    }

    get_all_hint_er_zhang(no_cai_shen_cards:Array<number>,cai_shen:Array<number>):Array<Comb>{
        let combs:Array<Comb> = [];
        if(no_cai_shen_cards.length + cai_shen.length < 2) return combs;
        if(no_cai_shen_cards.length > 0){
            let same_size_cards = this.get_all_same_size_cards(no_cai_shen_cards);
            //优先相同张数的
            for (let i = 0; i < same_size_cards.length; i++)
            {
                let cards_item = same_size_cards[i];
                if (cards_item.length == 2)
                {
                    combs.push(new Comb(CARD_TYPE.DUI_ZI,cards_item[0],cards_item));
                }
            }
            // 拆财神 拼单张成对子
            if(cai_shen.length>0){
                for (let i = 0; i < same_size_cards.length; i++)
                {
                    //优先相同张数的
                    let cards_item = same_size_cards[i];
                    if (cards_item.length == 1)
                    {
                        let cards_tmp = [];
                        cards_tmp.push(cards_item[0]);
                        cards_tmp.push(cai_shen[0]);
                        combs.push(new Comb(CARD_TYPE.DUI_ZI,cards_tmp[0],cards_tmp));
                    }
                }
            }
            //次选拆三张
            for (let i = 0; i < same_size_cards.length; i++)
            {
                let cards_item = same_size_cards[i];
                if (cards_item.length == 3)
                {
                    combs.push(new Comb(CARD_TYPE.DUI_ZI,cards_item[0],cards_item.slice(0,2)));
                }
            }
        }

        if(cai_shen.length > 0){
            let same_size_cards = this.get_all_same_size_cards(cai_shen);
            for (let i = 0; i < same_size_cards.length; i++)
            {
                let cards_item = same_size_cards[i];
                if(cards_item.length == 2){
                    combs.push(new Comb(CARD_TYPE.DUI_ZI,cards_item[0],cards_item.slice(0,2)));
                }
            }
            if(same_size_cards.length == cai_shen.length && cai_shen.length ==2){
                combs.push(new Comb(CARD_TYPE.DUI_ZI,cai_shen[0],cai_shen));
            }
        }

        return combs;
    }

    get_all_hint_san_zhang(no_cai_shen_cards:Array<number>,cai_shen:Array<number>):Array<Comb>{
        let combs = [];
        if(no_cai_shen_cards.length + cai_shen.length < 3) return combs;
        if(no_cai_shen_cards.length > 0){
            let same_size_cards = this.get_all_same_size_cards(no_cai_shen_cards);
            //优先相同张数的
            for (let i = 0; i < same_size_cards.length; i++)
            {
                let cards_item = same_size_cards[i];
                if (cards_item.length == 3)
                {
                    combs.push(new Comb(CARD_TYPE.SAN_ZHANG,cards_item[0],cards_item));
                }
            }
            // 拆财神 拼对子成三张
            if(cai_shen.length>=1){
                for (let i = 0; i < same_size_cards.length; i++)
                {
                    //优先相同张数的
                    let cards_item = same_size_cards[i];
                    if (cards_item.length == 2)
                    {
                        let cards_tmp = [];
                        cards_tmp.push(cards_item[0]);
                        cards_tmp.push(cards_item[1]);
                        cards_tmp.push(cai_shen[0]);
                        combs.push(new Comb(CARD_TYPE.SAN_ZHANG,cards_tmp[0],cards_tmp));
                    }
                }
            }
            // 拆财神 拼单张成三张
            if(cai_shen.length>=2){
                for (let i = 0; i < same_size_cards.length; i++)
                {
                    //优先相同张数的
                    let cards_item = same_size_cards[i];
                    if (cards_item.length == 1)
                    {
                        let cards_tmp = [];
                        cards_tmp.push(cards_item[0]);
                        cards_tmp.push(cai_shen[0]);
                        cards_tmp.push(cai_shen[1]);
                        combs.push(new Comb(CARD_TYPE.SAN_ZHANG,cards_tmp[0],cards_tmp));
                    }
                }
            }
        }
        return combs;
    }

    get_all_hint_er_shun(no_cai_shen_cards:Array<number>,cai_shen:Array<number>):Array<Comb>{
        let combs = [];

        if(no_cai_shen_cards.length + cai_shen.length < 6) return combs;

        //得到不重复大小的牌
        let all_same_size_cards = this.get_all_same_size_cards(no_cai_shen_cards);
        let cai_shen_count = cai_shen.length;
        let cards_target = [];
        //把大王和2移除掉
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let cards_item = all_same_size_cards[i];
            if (Card.getSize(cards_item[0]) != Card.SIZE._2 &&
                Card.getSize(cards_item[0]) != Card.SIZE._BJOKER &&
                Card.getSize(cards_item[0]) != Card.SIZE._RJOKER)
            {
                if(cards_item.length>=2){
                    cards_target.push(cards_item[0]);
                    cards_target.push(cards_item[1]);
                }else{
                    cards_target.push(cards_item[0]);
                }
            }
        }

        let min_len = 6-cai_shen_count;
        let max_len = 24;

        let combs_caishen = [];
        for(let length=min_len;length<=max_len;length++){
            for(let start=0;start<=cards_target.length-length;start++){
                let sub_cards = cards_target.slice(start,start+length);

                if(this.is_er_shun(sub_cards)){
                    combs.push(new Comb(CARD_TYPE.ER_SHUN,sub_cards[0],sub_cards));
                }
                if(this.is_er_shun_123(sub_cards)){
                    combs.push(new Comb(CARD_TYPE.ER_SHUN,sub_cards[0],sub_cards));
                }

                for(let cnt=1;cnt<=cai_shen.length;cnt++){
                    let sub_cai_shen_cards = cai_shen.slice(0,cnt);
                    let max_card = this.is_er_shun_cai_shen(sub_cards,cnt);
                    if(max_card != CARD_INVALID){
                        combs_caishen.push(new Comb(CARD_TYPE.ER_SHUN,max_card,sub_cards.concat(sub_cai_shen_cards)));
                    }
                    max_card = this.is_er_shun_cai_shen_123(sub_cards,cnt);
                    if(max_card != CARD_INVALID){
                        combs_caishen.push(new Comb(CARD_TYPE.ER_SHUN,max_card,sub_cards.concat(sub_cai_shen_cards)));
                    }
                }
            }
        }
        return this.get_no_simple_combs(combs.concat(combs_caishen));
    }

    get_all_hint_san_shun(no_cai_shen_cards:Array<number>,cai_shen:Array<number>):Array<Comb>{
        let combs = [];

        if(no_cai_shen_cards.length + cai_shen.length < 9) return combs;

        //得到不重复大小的牌
        let all_same_size_cards = this.get_all_same_size_cards(no_cai_shen_cards);
        let cai_shen_count = cai_shen.length;
        let cards_target = [];
        //把大王和2移除掉
        for (let i = 0; i < all_same_size_cards.length; i++)
        {
            let cards_item = all_same_size_cards[i];
            if (Card.getSize(cards_item[0]) != Card.SIZE._2 &&
                Card.getSize(cards_item[0]) != Card.SIZE._BJOKER &&
                Card.getSize(cards_item[0]) != Card.SIZE._RJOKER)
            {
                if(cards_item.length>=3){
                    cards_target.push(cards_item[0]);
                    cards_target.push(cards_item[1]);
                    cards_target.push(cards_item[2]);
                }else{
                    cards_target = cards_target.concat(cards_item);
                }
            }
        }

        let min_len = 6-cai_shen_count;
        let max_len = 27;

        let combs_caishen = [];
        for(let length=min_len;length<=max_len;length++){
            for(let start=0;start<=cards_target.length-length;start++){
                let sub_cards = cards_target.slice(start,start+length);

                if(this.is_san_shun(sub_cards) || this.is_san_shun_123(sub_cards)){
                    combs.push(new Comb(CARD_TYPE.SAN_SHUN,sub_cards[0],sub_cards));
                }
                for(let cnt=1;cnt<=cai_shen.length;cnt++){
                    let sub_cai_shen_cards = cai_shen.slice(0,cnt);
                    let max_card = this.is_san_shun_cai_shen(sub_cards,cnt);
                    if(max_card != CARD_INVALID){
                        combs_caishen.push(new Comb(CARD_TYPE.SAN_SHUN,max_card,sub_cards.concat(sub_cai_shen_cards)));
                    }
                    max_card = this.is_san_shun_cai_shen_123(sub_cards,cnt);
                    if(max_card != CARD_INVALID){
                        combs_caishen.push(new Comb(CARD_TYPE.SAN_SHUN,max_card,sub_cards.concat(sub_cai_shen_cards)));
                    }
                }
            }
        }
        return this.get_no_simple_combs(combs.concat(combs_caishen));
    }

    get_all_hint_san_dai_dui(no_cai_shen_cards:Array<number>,cai_shen:Array<number>):Array<Comb>{
        //TODO
        return null;
    }

    get_all_hint_fei_ji_win(no_cai_shen_cards:Array<number>,cai_shen:Array<number>):Array<Comb>{
        //TODO
        return null;
    }
    //获取所有炸弹(不带循环炸\连炸)
    get_all_hint_normal_boom(no_cai_shen_cards:Array<number>,cai_shen:Array<number>):Array<Comb>{
        let same_size_cards = this.get_all_same_size_cards(no_cai_shen_cards);
        //优先相同张数的
        let combs =[];
        let combs4= [];
        let combs5 = [];
        let combs6 = [];
        let combs7 = [];
        let combs8 = [];
        let combs9 = [];
        let combs10 = [];
        let combs11 = [];
        let combs12 = [];
        let combs_tianwang = [];

        if(cai_shen.length==4){
            combs_tianwang.push(new Comb(CARD_TYPE.TIAN_WANG,cai_shen[0],cai_shen));
        }

        for (let i = 0; i < same_size_cards.length; i++) {
            let cards_item = same_size_cards[i];
            if (cards_item.length == 4) {
                combs4.push(new Comb(CARD_TYPE.SI_ZHA, cards_item[0], cards_item));
            } else if (cards_item.length == 5) {
                combs5.push(new Comb(CARD_TYPE.WU_ZHA, cards_item[0], cards_item));
            } else if (cards_item.length == 6) {
                combs6.push(new Comb(CARD_TYPE.LIU_ZHA, cards_item[0], cards_item));
            } else if (cards_item.length == 7) {
                combs7.push(new Comb(CARD_TYPE.QI_ZHA, cards_item[0], cards_item));
            } else if (cards_item.length == 8) {
                combs8.push(new Comb(CARD_TYPE.BA_ZHA, cards_item[0], cards_item));
            }
        }

        combs = combs.concat(combs4, combs5, combs6, combs_tianwang, combs7, combs8);
        combs4 = [];
        combs5 = [];
        combs6 = [];
        combs7 = [];
        combs8 = [];
        //加上财神百搭
        for (let i = 0; i < same_size_cards.length; i++) {
            let cards_item = same_size_cards[i];
            let count = cards_item.length + cai_shen.length;
            if (count == 4) {
                combs4.push(new Comb(CARD_TYPE.SI_ZHA, cards_item[0], cards_item.concat(cai_shen)));
            } else if (count == 5) {
                combs5.push(new Comb(CARD_TYPE.WU_ZHA, cards_item[0], cards_item.concat(cai_shen)));
            } else if (count == 6) {
                combs6.push(new Comb(CARD_TYPE.LIU_ZHA, cards_item[0], cards_item.concat(cai_shen)));
            } else if (count == 7) {
                combs7.push(new Comb(CARD_TYPE.QI_ZHA, cards_item[0], cards_item.concat(cai_shen)));
            } else if (count == 8) {
                combs8.push(new Comb(CARD_TYPE.BA_ZHA, cards_item[0], cards_item.concat(cai_shen)));
            } else if (count == 9) {
                combs9.push(new Comb(CARD_TYPE.JIU_ZHA, cards_item[0], cards_item.concat(cai_shen)));
            } else if (count == 10) {
                combs10.push(new Comb(CARD_TYPE.SHI_ZHA, cards_item[0], cards_item.concat(cai_shen)));
            } else if (count == 11) {
                combs11.push(new Comb(CARD_TYPE.SHI_YI_ZHA, cards_item[0], cards_item.concat(cai_shen)));
            } else if (count == 12) {
                combs12.push(new Comb(CARD_TYPE.SHI_ER_ZHA, cards_item[0], cards_item.concat(cai_shen)));
            }
        }
        combs = combs.concat(combs4, combs5, combs6, combs_tianwang, combs7, combs8,combs9,combs10,combs11,combs12);
        return this.get_no_simple_combs(combs);
    }
}